package de.tum.se.sudoku.logic;

import de.tum.se.sudoku.impl.Cell;
import de.tum.se.sudoku.impl.Grid;
import de.tum.se.sudoku.impl.VariableCell;

import java.util.LinkedList;


/**
 * The BruteForce way to solve a Sudoku.
 * 
 * The idea is the following. First the entire grid is scanned for VariableCells.
 * These cells are then put into a list, so we can focus each iteration only on the
 * changeable cells. 
 * 
 * Then this list of cells is recursively changed. You could imagine the list as a 
 * chain of values starting with 11111111 and are counted up with each iteration.
 * So the next loop the chain would look like this 11111112, 11111113 ...
 * 11111119, 11111121
 * 
 * This is the BruteForce way to solve the Sudoku. 
 * 
 * 
 * @author Oliver
 *
 */
public class SolverBruteForce implements ISolver{

	@Override
	public Grid solve(Grid input) {
		
		Cell[][] cells = input.getCells();
		LinkedList<Cell> changeableCells = new LinkedList<Cell>();
		
		for (int i = 0; i < 9; i++){
			for (int j = 0; j < 9; j++){
				if (cells[i][j] instanceof VariableCell){
					cells[i][j].setValue(1);
					changeableCells.add(cells[i][j]);
				}
			}
		}
		
//		Integer listLength = changeableCells.size();
//		Double combinations = Math.pow(9, listLength.doubleValue());
//		Integer counter = 0;
//		Double progress;
		
		while(!input.isValid()){
			PrintListValues(changeableCells);
			BruteForceList(changeableCells);
//			counter++;
//			progress = (counter.doubleValue() / combinations) * 10000;
//			System.out.println(progress);
		}		
		
		return input;
	}

	

	private int BruteForceList(LinkedList<Cell> cellList) {
		if(cellList.size() == 0){
			return 1;	
		} 		
		else{
			Cell cell;
			cell = cellList.pop();
			int originalValue = cell.getValue();
			int newValue = originalValue + BruteForceList(cellList);
			if (newValue < 10){
				Cell newCell = new VariableCell(newValue);
				cellList.addFirst(newCell);
				return 0;
			}
			else{
				cell.setValue(1);
				cellList.addFirst(cell);
				return 1;
			}			
		}		
	}
	
	private void PrintListValues(LinkedList<Cell> changeableCells) {
		for(Cell cell : changeableCells){
			System.out.print(cell.getValue()+" ");
		}
		System.out.println();		
	}

}
